//Clase que genera los cromosomas.

package mx.unam.ia.algoritmos;

import mx.unam.ia.estructuras.ArbolExpresionBinario;

/**
 *
 * @author Juan Fco. Navarrete
 */

//Cada cromosoma esta formado por una cabeza y una cola.
// La cabeza contiene simbolos que representan funciones y
//terminales, mientras que la cola contiene solo terminales.
public class GeneradorCromosomas
{
    private int cabeza;
    private int cola;
    private double probabilidadOperacion;        

    public GeneradorCromosomas(int cabeza, int terminales, double probabilidadOperacion)
    {        
        this.cabeza = cabeza;
// La longitud de la cola depende de la cabeza y del numero de
//  argumentos de la funcion que tenga mas argumentos.
        this.cola = cabeza * (terminales - 1) + 1;      
        this.probabilidadOperacion = probabilidadOperacion;
    }

    public int getCabeza() //Se obtiene el valor de la cabeza
    {
        return cabeza;
    }

    public void setCabeza(int cabeza) //Se define el valor de la cabeza
    {
        this.cabeza = cabeza;
    }

    public double getProbabilidadOperacion() //Se obtiene la probabilidad de operacion
    {
        return probabilidadOperacion;
    }

    public void setProbabilidadOperacion(double probabilidadOperacion) //Se establece la probabilidad de operacion
    {
        this.probabilidadOperacion = probabilidadOperacion;
    }
       
   // Para cada valor dado, que sea menor que el valor de la cabeza se escoge un número aleatorio,
   // siempre y cuando sea menor se debe de comprobar si se trata de una operación 
   // unaria o binaria, sino cumple la condicion es un terminal y se obtienen los valores respectivos.
   // Para la cola solo es necesario obtener un terminal
    //La expresion se devuleve en una cadena.
    public String generarGen() //Gerador de genes.
    {
        StringBuilder expresion = new StringBuilder();
        for (int i = 0; i < cabeza; i++)
        {
            double aleatorio = Math.random();            
            if(aleatorio < probabilidadOperacion)
            {
                if(aleatorio < (probabilidadOperacion / 2))
                    expresion.append(OperacionUnaria.obtenerOperacion());
                else
                    expresion.append(OperacionBinaria.obtenerOperacion());
            }
            else            
                expresion.append(Terminal.obtenerTerminal());
        }
        for (int i = 0; i < cola; i++)        
            expresion.append(Terminal.obtenerTerminal());
        return expresion.toString();
    }

//Para cada valor dado que sea menor al número de cromosomas se genera una cadena de símbolos
// (gen), ademas de que se obtiene su expresion del arbol binario", despues de eso se crea un
//nuevo cromosoma.
    public Cromosoma[] generarCromosomas(int numeroCromosomas)
    {
        Cromosoma[] cromosomas = new Cromosoma[numeroCromosomas];
        for (int i = 0; i < numeroCromosomas; i++)
        {
            String gen = generarGen();            
            ArbolExpresionBinario arbol = ArbolExpresionBinario.generar(gen);
            Cromosoma cromosoma = new Cromosoma(gen);
            cromosomas[i] = cromosoma;
        }
        return cromosomas;
    }
}
